// file: cb.cc
//
// this file contains an implementation of the circular buffer class.
// for convenience, we have grouped all methods into a single file.
//
//
//-----------------------------------------------------------------------------

// system include files
//
#include <stdlib.h>
#include <memory.h>

// isip include files
//
#include "cb.h"

//-----------------------------------------------------------------------------
//
// class: Circular_buffer
//
// description: a circular buffer class implemented as a linear array
//              with logic that checks for wrap-around of pointers
//
//-----------------------------------------------------------------------------
// constructors/destructors
//-----------------------------------------------------------------------------
Circular_buffer::Circular_buffer() {
  idx_d = -1;
  size_d = 0;
  buf_d = (float*)NULL;
}

Circular_buffer::~Circular_buffer() {
  idx_d = -1;
  size_d = 0;
  delete [] buf_d;
}

//-----------------------------------------------------------------------------
// allocation
//-----------------------------------------------------------------------------
void Circular_buffer::allocate_cc(int num_elements) {

  // check if a buffer already exists
  //
  if (buf_d != (float*)NULL)
    {delete [] buf_d;}

  // allocate a buffer
  //
  idx_d = 0;
  size_d = num_elements;
  buf_d = new float[size_d];

  // clear memory
  //
  memset(buf_d, (int)0, size_d*sizeof(float));

  // exit gracefully
  //
}

//-----------------------------------------------------------------------------
// indexing methods
//-----------------------------------------------------------------------------
int Circular_buffer::add_cc(float new_value) {

  // increment the pointer
  //
  idx_d++;

  if (idx_d >= size_d)
    {idx_d -= size_d;}
  else if (idx_d < (int)0)
    {idx_d += size_d;}
    
  // assign the value
  //
  buf_d[idx_d] = new_value;

  // return the new pointer
  //
  return idx_d;
}

//-----------------------------------------------------------------------------
// overloaded operators
//-----------------------------------------------------------------------------
float Circular_buffer::operator() (int index) {

  // note that the index is actually an offset from idx_d
  //
  int idx = idx_d + index;

  // check the index
  //
  if (idx > size_d)
    {idx -= size_d;}
  else if (idx < (int)0)
    {idx += size_d;}

  // return the corresponding value
  //
  return buf_d[idx];
}
